AWS Systems Manager による AWS IoT Greengrass デバイスサポートを試してみる
先日の re:Invent 2021 期間中に AWS Systems Manager が AWS IoT Greengrass デバイスをサポートするアップデートがありましたので試してみました。
従来のマネージドインスタンス登録との違い
これまで、オンプレミスサーバや Raspberry Pi などのエッジデバイスでも要件(OSがサポート対象である等)が合えば、エッジデバイスでも AWS Systems Manager のマネージドインスタンスとして登録することが可能でした。
今回のアップデートで AWS Systems Manager Agent (SSM Agent) が AWS IoT Greengrass (V2)のコンポーネントとして提供されることになったので、このコンポーネントをデプロイするだけで「AWS Systems Manager Agent のインストール」と「アクティベーション」を自動で実行してくれるようになりました。
注意点
今回のリリースで提供される Systems Manager Agent コンポーネント がサポートするプラットフォームは下記のとおりです。Greengrass コア自体は Armv7 や Windows をサポートしていますが、このコンポーネントが動作できる環境は限定的なので注意が必要です。
- 64bit Linux 上の Greengrass コアデバイス
- Armv8(AArch64)または x86_64
検証環境
今回は下記の環境で動作検証を行いました。
- Raspberry Pi 4B
- ubuntu 20.04.3 LTS 64bit
上記の環境に Greengrass (V2) 環境を用意していますが、本記事では Greengrass コアデバイスのセットアップは省略します。具体的な手順については下記を参考にしてみてください。
それでは、ここから実際の手順を見ていきたいと思います。
IAM の設定
まずは必要な IAM の設定を行います。デバイスが AWS Systems Manager と通信するために IAM のサービスロールを作成します。まず手元のPCで適当なディレクトリで下記の json ファイルを用意します。
SSMService-Trust.json
として作成
{ "Version": "2012-10-17", "Statement": { "Effect": "Allow", "Principal": { "Service": "ssm.amazonaws.com" }, "Action": "sts:AssumeRole" } }
作成したポリシーの JSON ファイルに対して AWS CLI で IAM Role を作成します。
$ aws iam create-role \ --role-name SSMServiceRole \ --assume-role-policy-document file://SSMService-Trust.json
次に、デバイスがAWS SystemsManager サービスのコア機能を使用できるように AmazonSSMManagedInstanceCore
という AWS マネージドポリシーを、先程作成した IAM Role にアタッチします。
$ aws iam attach-role-policy \ --role-name SSMServiceRole \ --policy-arn arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
最後に、Greengrass コアデバイスで利用する IAM Role である Token Exchange Service(TES)に Systems Manager を利用する権限を追加します。
Greengrass コアソフトインストール時のデフォルト設定では、TES の IAM Role 名は GreengrassV2TokenExchangeRole
になります。
先程と同じように下記内容のポリシーを記載した JSON ファイルを作成します。(ssm-agent-component-policy.json
)
{ "Version": "2012-10-17", "Statement": [ { "Action": [ "iam:PassRole" ], "Effect": "Allow", "Resource": [ "arn:aws:iam::[YOUR_AWS_ACCOUNT_ID]:role/SSMServiceRole" ] }, { "Action": [ "ssm:AddTagsToResource", "ssm:RegisterManagedInstance" ], "Effect": "Allow", "Resource": "*" } ] }
次にポリシーを作成します。ポリシー名は「GreengrassSSMAgentComponentPolicy」としました。
$ aws iam create-policy \ --policy-name GreengrassSSMAgentComponentPolicy \ --policy-document file://ssm-agent-component-policy.json
IAM ポリシーが作成できたら、Greengrass の IAM Role である GreengrassV2TokenExchangeRole にアタッチします。ポリシーの ARN は利用環境に合わせてください。
$ aws iam attach-role-policy \ --role-name GreengrassV2TokenExchangeRole \ --policy-arn arn:aws:iam::[YOUR_AWS_ACCOUNT_ID]:policy/GreengrassSSMAgentComponentPolicy
AWS Systems Manager Agent のインストール
今回利用するコンポーネントはエージェントのインストールも自動で行ってくれるので、エージェントの事前インストールは必要ありません。 もし事前に手動でインストールする場合は下記ページを参考にしてください。(下記は Ubuntu 環境へのインストール手順です)
(事前にエージェントをインストールする場合は)上記ドキュメントにある通り、Snap パッケージとしてインストールします。
$ sudo snap install amazon-ssm-agent --classic
AWS Systems Manager Agent コンポーネントのデプロイ
最後に AWS Systems Manager Agent コンポーネントをデプロイを行います。
まず、AWS IoT Greengrass のコンソールで「コンポーネント」の画面から「パブリックコンポーネント」タブを開いて、「aws.greengrass.SystemsManagerAgent」コンポーネントをクリックします。
「aws.greengrass.SystemsManagerAgent」コンポーネントの画面が開いたら、そのまま「デプロイ」ボタンをクリックしてデプロイ作業に進みます。
デプロイする対象を選択します。今回は既存のものを選択しました。
ターゲットの指定は必要に応じて変更してください。
次の画面でデプロイするコンポーネントを選択します。下側の「パブリックコンポーネント」に「aws.greengrass.SystemsManagerAgent」にチェックが入っていることを確認します。
次の画面でコンポーネントの設定を行いますので、「aws.greengrass.SystemsManagerAgent」を選択して「コンポーネントを設定」ボタンをクリックします。
「マージする設定」欄に要件に応じた内容で設定します。
AWS Systems Manager がインストールされていない場合は下記の内容で設定します。
{ "SSMRegistrationRole": "SSMServiceRole", "SSMResourceTags": [ { "Key": "Greengrass", "Value": "true" } ], "SSMOverrideExistingRegistration": false }
SSMRegistrationRole
:AWS Systems Manager を利用するために最初に作成した IAM Role 名SSMResourceTags
:AWS Systems Manager に登録されたノードを管理するタグ(オプション)SSMOverrideExistingRegistration
:コンポーネントではなく手動でエージェントを実行している場合、エージェント登録を上書きします。- エージェントは未インストールなので
false
にセットします。
- エージェントは未インストールなので
事前に手動でエージェントをインストールした場合は "SSMOverrideExistingRegistration": true
とします。
公式ドキュメントには SSMOverrideRegistration というパラメータが書かれており、SSMOverrideExistingRegistrationに関する記載がありません。
しかし、コンポーネントのデフォルト設定では、SSMOverrideExistingRegistrationが書かれているので、SSMOverrideExistingRegistrationが正しいパラメータになります。
実際に SSMOverrideRegistrationではマネージドインスタンスとして登録できないケースがありました。
{ "SSMRegistrationRole": "SSMServiceRole", "SSMResourceTags": [ { "Key": "Greengrass", "Value": "true" } ], "SSMOverrideExistingRegistration": true }
コンポーネントの設定ができたら「変更済み?」列が「Yes」になります。
「詳細設定を構成」の画面では、IoT Jobs の設定です。必要に応じて設定してください。
(今回はそのまま次へ進みました)
最後にこれまでの設定をレビューして問題無ければ「デプロイ」をクリックします。
コンポーネントのデプロイは IoT Jobs の機能が使われるので、デプロイ開始後は「デプロイ」画面の「IoT ジョブ」のリンクから実行状況が確認できます。
ジョブのステータスが「成功しました」になればデプロイ完了です。
デプロイの途中状況や結果は、デバイス側のログからも確認可能です。デバイス側はデフォルトで /greengrass/v2/logs/greengrass.log
に実行結果が表示されます。
下記のようなログが出ていればデプロイ成功です。
2021-12-09T07:19:52.254Z [INFO] (Thread-3) com.aws.greengrass.deployment.IotJobsHelper: Job status update was accepted. {Status=SUCCEEDED, ThingName=xxxxx, JobId=004a0ffc-xxxxxxxxxxxxxxxx}
/greengrass/v2/logs/aws.greengrass.SystemsManagerAgent.log
は、コンポーネント単体のログになります。こちらにもデプロイ時の詳細が出ています。下記のようなログが出ていれば正常にデプロイできています。
2021-12-09T07:19:38.253Z [INFO] (Copier) aws.greengrass.SystemsManagerAgent: Startup script exited. {exitCode=0, serviceName=aws.greengrass.SystemsManagerAgent, currentState=STARTING}
デプロイ結果の確認
正常にコンポーネントのデプロイが完了していれば、AWS IoT Greengrass のコンソール側から確認が可能です。対象のデプロイ画面にある「コアデバイス名」のリンクからコアデバイスの詳細画面を開きます。
正常にコンポーネントがデプロイされてAWS Systems Manager に登録されると、下記画像のように「Systems Manager インスタンス」という項目が新たに表示されるようになります。
リンクをクリックすると、AWS Systems Manager の画面を開くことができます。
フリートマネージャーの画面で、登録されたデバイスを確認することができました。エージェント経由で OS の種類やデバイスのIPアドレスを確認することができます。
今回のアップデートの内容は以上までとなりますが、せっかくなので AWS Systems Manager を使って少し遊んでみたいと思います。
AWS Systems Manager からコマンドを実行する
それでは、試しに「Run Command」を試してみたいと思います。先程の画面で「インスタンスアクション」のプルダウンから「Execute Run command」をクリックすると、Run Command の画面が開きます。
AWS Systems Manager のメニューから「Run Command」をクリックしても同じ画面に遷移できます。
Run Command の画面が開いたら、実行したいコマンドドキュメントを指定します。
今回は Linux のコマンドを実行したいので、検索画面に「RunShellScript」といったワードで検索して対象のコマンドドキュメントを探します。
検索で見つかった「AWS-RunShellScript」 というコマンドドキュメントを選択して、「コマンドのパラメータ」というテキストエリアに実行したいコマンドを入力します。
今回は下記のようなコマンドを実行してみたいと思います。
echo "##### release info #####" lsb_release -a echo "##### hostname #####" hostname
次にコマンドを実行するターゲットを指定します。コンポーネントのデプロイ時に対象デバイスにタグを付けたので、そのタグが付いているデバイスを対象にしたいと思います。
今回は1台だけですが、同じタグの付いた複数のデバイスをターゲットにすることも可能になります。(複数のタグがデバイスに付いていれば、ターゲットの指定でも複数のタグをセットすることが可能です)
最後に「Add」ボタンをクリックするのを忘れないようにしましょう。
タグの指定ができれば、下記のような表示になります。
その他の出力オプションやSNS通知などの設定はデフォルトのままにして「実行」します。
コマンドの実行中は下記のように「実行中」のステータスになります。ステータスは実行ターゲット毎に表示されます。(今回は1台だけなので1つしか表示されていません)
コマンドの実行が終わるとステータスが「成功」になります。
コマンドの実行結果はコンソール上で確認可能です。対象のインスタンス ID をクリックするか、「出力の表示」をクリックします。
出力画面で、標準出力と標準エラー出力の内容を確認できます。
今回実行した lsb_release
コマンドはポイントリリースの適用状態を表示するものですが、LSBパッケージがインストールされていないと、下記のようにエラーも返ります。
参考までに、デバイス上で同じコマンドを実行すると下記のようになります。
$ lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 20.04.3 LTS Release: 20.04 Codename: focal
AWS Cloudwatch Logs に結果を出力する
AWS Systems Manager のコンソールでは、コマンド実行結果の最初の2500文字までしか表示することができません。 2500文字を超える場合、実行結果の全体を確認するには Amazon S3 や AWS CloudWatch Logs から結果を確認する必要があります。
Amazon S3 への出力は以前から対応していましたが オブジェクトをダウンロードして確認するなど少々面倒な部分がありました。AWS CloudWatch Logs であればコンソールでほぼリアルタイムに気軽に確認できるので便利です。
AWS Cloudwatch Logs 出力に必要な IAM の権限を追加
これまでの設定では AWS Cloudwatch Logs に出力する権限が無いので、最初に作った IAM Role SSMServiceRole
に AWS マネージドポリシーである CloudWatchAgentServerPolicy
ポリシーを追加でアタッチします。
$ aws iam attach-role-policy \ --role-name SSMServiceRole \ --policy-arn arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy
追加したポリシー CloudWatchAgentServerPolicy
は下記のような権限を持っているので、実行結果をログストリームに書き込んだり、指定されたロググループが無ければ新規にロググループを作成することができるようになります。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "cloudwatch:PutMetricData", "ec2:DescribeVolumes", "ec2:DescribeTags", "logs:PutLogEvents", "logs:DescribeLogStreams", "logs:DescribeLogGroups", "logs:CreateLogStream", "logs:CreateLogGroup" ], "Resource": "*" }, { "Effect": "Allow", "Action": [ "ssm:GetParameter" ], "Resource": "arn:aws:ssm:*:*:parameter/AmazonCloudWatch-*" } ] }
IAM の設定ができたら、コマンド実行の「出力オプション」で下記のようにロググループを指定せずにコマンドを実行した場合を見てみます。
この場合は、下記のように AWS CloudWatch Logs に /aws/ssm/SystemsManagerDocumentName
という形式で自動的にロググループを作成します。今回は /aws/ssm/AWS-RunShellScript
というロググループになります。
ログストリームは下記のようになります。
CommandID/InstanceID/PluginID/stdout
CommandID/InstanceID/PluginID/stderr
ログストリームの中身を見ると、コマンドの実行結果を確認することができました。
こちらは標準エラー出力の結果です。標準出力と標準エラー出力でそれぞれのログストリームに結果が書き込まれていることが確認できました。
コマンド実行時にロググループを指定することもできます。存在しないロググループ名であれば、自動的に作成されます。
コマンドを実行すると、指定したロググループ(greengrass-device-myubuntu-ssm
)が作成されてログストリームを確認することができました。
AWS CloudWatch Logs への出力を有効にしていると、コマンドの実行結果にあるリンクから直接 AWS CloudWatch Logs の画面に遷移することもできます。
下記のように、標準出力と標準出力エラーのリンクがそれぞれのログストリームに対応しています。
最後に
今回のアップデートでは、AWS IoT Greengrass のコアデバイスに対して、より簡単に AWS Systems Manager が利用できるようになったというものです。
オンプレミスサーバや IoTデバイス における AWS Systems Manager の利用自体は以前から可能でしたが、AWS IoT Greengrass を利用していれば簡単に導入できるようになったので、ぜひ試していただければと思います。